package mylibrary.io.nio.nonBlock.sample2;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class DownloadServer {

	private Selector selector;
	private ServerSocketChannel serverSocket;
	private Map map = new HashMap();
	
	
	public void init() {
		try {
			selector = Selector.open();	
			serverSocket = ServerSocketChannel.open();
			serverSocket.configureBlocking(false);
			
			serverSocket.socket().bind(new InetSocketAddress("localhost", 1234));
			serverSocket.register(selector, SelectionKey.OP_ACCEPT);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void accept(SelectionKey key) throws Exception {
		
		if(key.isAcceptable()) {
			ServerSocketChannel channel = (ServerSocketChannel) key.channel();
			SocketChannel socketChannel = channel.accept();
			socketChannel.configureBlocking(false);
			socketChannel.register(selector, SelectionKey.OP_READ);
			//map.put(socketChannel, new Handle());
		}
	}
	
	public void run() throws Exception {
		
		while(true) {
			selector.select();
			Iterator it = selector.selectedKeys().iterator();
			while(it.hasNext()) {
				SelectionKey key = (SelectionKey) it.next();
				it.remove();
				if(key.isValid()) {
					System.out.println("It's valid");
					if(key.isAcceptable()) {
						System.out.println("It's acceptable");
						accept(key);
					}else if(key.isReadable()) {
						SocketChannel readChannel = (SocketChannel) key.channel();
						ByteBuffer buff = ByteBuffer.allocate(1024);
						int count = readChannel.read(buff);
						System.out.println("The content is " + new String(buff.array()));
							
						readChannel.configureBlocking(false);
						readChannel.register(selector, SelectionKey.OP_WRITE);
					} else if(key.isWritable()) {
						SocketChannel writeChannel = (SocketChannel) key.channel();
						ByteBuffer buff = ByteBuffer.allocate(1024);
						
						FileChannel inputFile = new FileInputStream("D:\\Study\\EJB.pdf").getChannel();
						while(inputFile.read(buff) != -1) {
							System.out.println("Write process");
							buff.flip();
							writeChannel.write(buff);
							buff.clear();
						}
						System.out.println("Write Finished");
						inputFile.close();
						writeChannel.close();
						key.cancel();
					}
				}
			}
		}
	}
	
	private class Handle {
		private StringBuilder message = new StringBuilder();
		private boolean wirteOk = true;
		private ByteBuffer buff = ByteBuffer.allocate(1024);
		private FileChannel fileChannel;
		private String fileName;
		
		private void handle(SelectionKey key) throws IOException {
			
			System.out.println("Enter handle method");
			
			if(key.isReadable()) {
				
				SocketChannel socketChannel = (SocketChannel) key.channel();
				
				buff.clear();
				int count = socketChannel.read(buff);
				if(count == -1) {
					socketChannel.close();
					key.cancel();
					return;
				} else {
					message.append(new String(buff.array()));
				}
				
				System.out.println("The received name is " + message);
				
				socketChannel.register(selector, SelectionKey.OP_WRITE);
				
				if(key.isWritable()) {
					
					SocketChannel client = (SocketChannel) key.channel();
					
					fileChannel = new FileInputStream("D:\\Study\\EJB.pdf").getChannel();
					
					buff.clear();
					
					fileChannel.read(buff);
					
					buff.flip();
					
					socketChannel.write(buff);
				}
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		DownloadServer test = new DownloadServer();
		test.init();
		test.run();
	}
	
}
